﻿using HalkSee.Dto;
using OtpNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Android.InputMethodServices.Keyboard;

namespace HalkSee.Helper
{
    public class InfoHelper
    {
        private static string _SN { get; set; }
        public static string SN
        {
            get
            {
                if (_SN == null)
                {
                    _SN = SecureStorage.Default.GetAsync("sn").Result;
                    if (_SN == null)
                    {
                        var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToArray();
                        var now = DateTime.Now;
                        _SN = $"{map[now.Year - 2023]}{map[now.Month]}{map[now.Day]}{now:HHmmssf}";
                        SecureStorage.Default.SetAsync("sn", _SN).GetAwaiter().GetResult();
                    }
                }
                return _SN;
            }
        }

        private static List<DeviceDto> _Devices { get; set; }
        public static List<DeviceDto> Devices 
        { 
            get
            {
                if(_Devices == null)
                {
                    _Devices = new List<DeviceDto>();
                    var data = SecureStorage.Default.GetAsync("device").Result;
                    if (!string.IsNullOrEmpty(data))
                    {
                        _Devices = data.Trim()
                                .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                .Select(m => m.Split(' '))
                                .Select(m => new DeviceDto { SN = m[0], OtpKey = m[1] })
                                .ToList();
                    }
                }
                return _Devices;
            }
        }

        public static void AddDevice(DeviceDto item)
        {
            Devices.Add(item);
            var data = string.Join(',', Devices.Select(m => $"{m.SN} {m.OtpKey}"));
            SecureStorage.Default.SetAsync("device", data).GetAwaiter().GetResult();
        }

        public static void RemoveDevice(DeviceDto item)
        {
            Devices.Remove(item);
            var data = "";
            if (Devices.Count > 0)
                data = string.Join(',', Devices.Select(m => $"{m.SN} {m.OtpKey}"));
            SecureStorage.Default.SetAsync("device", data).GetAwaiter().GetResult();
        }

        private static string key { get; set; }
        public static string MyOtpKey
        {
            get
            {
                if (key == null)
                {
                    key = SecureStorage.Default.GetAsync("OtpKey").Result;
                    if (key == null)
                    {
                        key = Guid.NewGuid().ToString("N").ToUpper()[..8];
                        SecureStorage.Default.SetAsync("OtpKey", key).GetAwaiter().GetResult();
                    }
                }
                return key;
            }
        }

        public static string GetOtpCode(string key)
        {
            var otp = new Totp(Encoding.UTF8.GetBytes(key), 30, OtpHashMode.Sha1);
            return otp.ComputeTotp(DateTime.UtcNow);
        }

        public static bool VerifyOtpCode(string key, string code)
        {
            var otp = new Totp(Encoding.UTF8.GetBytes(key), 30, OtpHashMode.Sha1);
            var time = DateTime.UtcNow.AddSeconds(-30 * 10); //前5分钟
            for (int i = 0; i < 20; i++) //允许误差±5分钟
            {
                var _code = otp.ComputeTotp(time);
                if (_code == code)
                    return true;
                time = time.AddSeconds(30);
            }
            return false;
        }
    }
}
